/**
 * 该文件可自行根据业务逻辑进行调整
 */
import type { RequestClientOptions } from '@vben/request';

import { useAppConfig } from '@vben/hooks';
import { preferences } from '@vben/preferences';
import {
  authenticateResponseInterceptor,
  errorMessageResponseInterceptor,
  RequestClient,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';

import { message } from 'ant-design-vue';

import { useAuthStore } from '#/store';
import { removeAuditFields } from '#/utils/form';

import { refreshTokenApi } from './core';

const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);

// 全局标志：是否正在处理 token 过期
let isHandlingTokenExpired = false;

function createRequestClient(baseURL: string, options?: RequestClientOptions) {
  const client = new RequestClient({
    ...options,
    baseURL,
  });

  /**
   * 重新认证逻辑
   */
  async function doReAuthenticate() {
    // 如果已经在处理 token 过期，直接返回
    if (isHandlingTokenExpired) {
      return;
    }

    isHandlingTokenExpired = true;
    console.warn('Access token or refresh token is invalid or expired. ');
    const accessStore = useAccessStore();
    const authStore = useAuthStore();
    accessStore.setAccessToken(null);

    if (
      preferences.app.loginExpiredMode === 'modal' &&
      accessStore.isAccessChecked
    ) {
      accessStore.setLoginExpired(true);
    } else {
      await authStore.logout();
    }

    // 重置标志（在跳转到登录页后）
    setTimeout(() => {
      isHandlingTokenExpired = false;
    }, 1000);
  }

  /**
   * 刷新token逻辑
   */
  async function doRefreshToken() {
    const accessStore = useAccessStore();
    const resp = await refreshTokenApi();
    const newToken = resp.data;
    accessStore.setAccessToken(newToken);
    return newToken;
  }

  function formatToken(token: null | string) {
    return token ? `Bearer ${token}` : null;
  }

  // 请求头处理
  client.addRequestInterceptor({
    fulfilled: async (config) => {
      const accessStore = useAccessStore();

      // 🔍 调试：检查 token 是否存在
      if (import.meta.env.DEV) {
        console.log(`🔍 [请求拦截器] ${config.method?.toUpperCase()} ${config.url}`, {
          'accessToken 存在': !!accessStore.accessToken,
          'accessToken 长度': accessStore.accessToken?.length || 0,
          'accessToken 前20字符': accessStore.accessToken?.substring(0, 20) || 'null',
        });
      }

      config.headers.Authorization = formatToken(accessStore.accessToken);
      config.headers['Accept-Language'] = preferences.app.locale;

      // 🧹 自动移除审计字段（仅对 POST 和 PUT 请求）
      if (
        config.data &&
        typeof config.data === 'object' &&
        (config.method?.toUpperCase() === 'POST' ||
          config.method?.toUpperCase() === 'PUT')
      ) {
        // 检查是否包含审计字段
        const hasAuditFields =
          'createTime' in config.data ||
          'createBy' in config.data ||
          'updateTime' in config.data ||
          'updateBy' in config.data ||
          'createName' in config.data ||
          'updateName' in config.data;

        if (hasAuditFields) {
          config.data = removeAuditFields(config.data);
          if (import.meta.env.DEV) {
            console.log('🧹 [请求拦截器] 已自动移除审计字段');
          }
        }
      }

      // 调试日志：打印请求信息（仅开发环境）
      if (
        import.meta.env.DEV &&
        (config.method?.toUpperCase() === 'POST' ||
          config.method?.toUpperCase() === 'PUT' ||
          config.method?.toUpperCase() === 'GET')
      ) {
        // eslint-disable-next-line no-console
        console.log(`📤 [请求详情] ${config.method?.toUpperCase()} ${config.url}`, {
          Authorization: config.headers.Authorization ? '✅ 已设置' : '❌ 未设置',
          headers: config.headers,
          data: config.data,
          params: config.params,
        });
      }

      return config;
    },
  });

  // 处理返回的响应数据格式
  client.addResponseInterceptor({
    fulfilled: (response) => {
      const { config, data: responseData } = response;

      // 如果配置了 responseReturn 为 'raw'，直接返回原始响应
      if (config.responseReturn === 'raw') {
        return response;
      }

      // 如果响应数据不是对象，直接返回数据
      if (!responseData || typeof responseData !== 'object') {
        return config.responseReturn === 'response' ? response : responseData;
      }

      // 格式1: { respCode: 0 | 1, datas: {...} | [...], respMsg: "..." }
      // respCode: 0 = 成功, 1 或其他非 0 值 = 失败
      if ('respCode' in responseData) {
        const { respCode, datas, respMsg } = responseData;
        const isSuccess = respCode === 0;

        if (!isSuccess) {
          // respCode 非 0 表示失败
          // 注意：这里的 respCode 是业务状态码，不是 HTTP 状态码
          // 登录失败时，respCode 可能是 401，但这不是 HTTP 401（token 过期）
          // 所以不需要特殊处理，直接抛出错误即可
          const error: any = new Error(respMsg || 'Request failed');
          error.response = {
            ...response,
            data: responseData, // 保存完整的响应数据
          };
          error.respCode = respCode; // 保存业务状态码
          error.respMsg = respMsg; // 保存错误消息
          throw error;
        }

        // 如果 datas 是对象且包含 records 字段（MyBatis-Plus 分页结构）
        // 转换为标准格式：{ list, total, pageNum, pageSize }
        if (datas && typeof datas === 'object' && 'records' in datas) {
          const standardFormat = {
            list: datas.records || [],
            total: datas.total || 0,
            pageNum: datas.current || 1,
            pageSize: datas.size || 10,
          };
          return config.responseReturn === 'response' ? response : standardFormat;
        }

        return config.responseReturn === 'response' ? response : datas;
      }

      // 格式2: { code: 0, data: {...}, message: "..." } 或 { code: 401, msg: "...", data: null }
      if ('code' in responseData) {
        const { code, data } = responseData;
        const successCode = 0;

        if (code !== successCode) {
          // 兼容 message 和 msg 两种字段
          const errorMessage =
            responseData.message || responseData.msg || 'Request failed';

          // 如果是 401 未授权错误，抛出特殊错误以便认证拦截器处理
          if (code === 401) {
            const error: any = new Error(errorMessage);
            error.response = response;
            error.response.status = 401;
            throw error;
          }

          throw new Error(errorMessage);
        }

        return config.responseReturn === 'response' ? response : data;
      }

      // 如果都不是标准格式，返回原始数据
      console.warn(
        `API ${config.url} returned data without standard format, returning raw data`,
      );
      return config.responseReturn === 'response' ? response : responseData;
    },
  });

  // token过期的处理
  client.addResponseInterceptor(
    authenticateResponseInterceptor({
      client,
      doReAuthenticate,
      doRefreshToken,
      enableRefreshToken: preferences.app.enableRefreshToken,
      formatToken,
    }),
  );

  // 通用的错误处理,如果没有进入上面的错误处理逻辑，就会进入这里
  client.addResponseInterceptor(
    errorMessageResponseInterceptor((msg: string, error) => {
      // 如果正在处理 token 过期，不显示任何错误消息
      if (isHandlingTokenExpired) {
        return;
      }

      // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理，根据不同的 code 做不同的提示，而不是直接使用 message.error 提示 msg
      // 当前mock接口返回的错误字段是 error 或者 message 或者 msg 或者 respMsg
      const responseData = error?.response?.data ?? {};
      const status = error?.response?.status;

      // 区分 HTTP 401（token 过期）和业务 401（登录失败）
      // 只有 HTTP 状态码是 401 且不是登录接口时，才不显示错误消息
      const isLoginRequest = error?.config?.url?.includes('/auth/login');
      if (status === 401 && !isLoginRequest) {
        console.warn('Token expired or invalid, redirecting to login...');
        return;
      }

      // 兼容多种错误消息字段（优先使用后端返回的具体错误消息）
      const errorMessage =
        responseData?.respMsg ?? // 后端自定义格式
        responseData?.msg ?? // 后端自定义格式
        responseData?.message ?? // 标准格式
        responseData?.error ?? // 其他格式
        error?.message ?? // 从 Error 对象中获取
        msg; // 默认消息

      // 显示错误消息
      message.error(errorMessage);
    }),
  );

  return client;
}

export const requestClient = createRequestClient(apiURL, {
  responseReturn: 'data',
});

export const baseRequestClient = new RequestClient({ baseURL: apiURL });
